﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace Mengsk.ProxyDelivery.Service
{
    public class Parameter
    {
        public const string TYPE_MAP = "map";
        public const string TYPE_LIST = "list";
        public const string TYPE_ARRAY = "array";
        public const string TYPE_STRING = "string";
        public const string TYPE_ENUM = "enum";
        public const string TYPE_INT = "int";
        public const string TYPE_LONG = "long";
        public const string TYPE_FLOAT = "float";
        public const string TYPE_DOUBLE = "double";
        public const string TYPE_DATETIME = "datetime";
        public const string TYPE_BOOL = "boolean";

        public string Name { get; set; }

        public object Value { get; set; }

        public List<ParameterEntry> Entries { get; private set; }

        public Parameter()
        {
            this.Entries = new List<ParameterEntry>();
        }

        public Parameter(string name, object value)
        {
            this.Name = name;
            this.Value = value;
        }

        private string GetObjectType(object value)
        {
            if (value == null)
            {
                throw new ArgumentException("value");
            }

            if (value is bool)
            {
                return TYPE_BOOL;
            }

            if (value is Enum)
            {
                return TYPE_ENUM;
            }

            if (value.GetType() == typeof(int) || value.GetType() == typeof(short) || value.GetType() == typeof(byte))
            {
                return TYPE_INT;
            }

            if (value.GetType() == typeof(long))
            {
                return TYPE_LONG;
            }

            if (value.GetType() == typeof(string))
            {
                return TYPE_STRING;
            }

            if (value.GetType() == typeof(DateTime))
            {
                return TYPE_DATETIME;
            }

            if (value.GetType() == typeof(float) || value.GetType() == typeof(Single))
            {
                return TYPE_FLOAT;
            }

            if (value.GetType() == typeof(double))
            {
                return TYPE_DOUBLE;
            }

            if (value.GetType().IsArray)
            {
                return TYPE_ARRAY;
            }

            Type[] types = value.GetType().GetInterfaces();
            if (types.Any(obj => obj.Name.Contains("IDictionary")))
            {
                return TYPE_MAP;
            }

            if (types.Any(obj => obj == typeof(System.Collections.IEnumerable)))
            {
                return TYPE_LIST;
            }

            throw new Exception("无法认识的类型:" + value.GetType().FullName);
        }

        public XElement ToXElement()
        {
            String type = this.GetObjectType(Value);
            if (type == TYPE_STRING || type == TYPE_INT || type == TYPE_LONG)
            {
                return new XElement("parameter", new XAttribute("name", Name), new XAttribute("type", type), Value);
            }

            if (type == TYPE_ENUM)
            {
                return new XElement("parameter", new XAttribute("name", Name), new XAttribute("type", TYPE_INT), (int)Value);
            }

            if (type == TYPE_DATETIME)
            {
                return new XElement("parameter", new XAttribute("name", Name), new XAttribute("type", type), ((DateTime)Value).ToString("yyyy-MM-dd HH:mm:ss"));
            }

            if (type == TYPE_FLOAT)
            {
                return new XElement("parameter", new XAttribute("name", Name), new XAttribute("type", type), ((float)Value).ToString("F2"));
            }

            if (type == TYPE_DOUBLE)
            {
                return new XElement("parameter", new XAttribute("name", Name), new XAttribute("type", type), ((double)Value).ToString("F2"));
            }

            if(type==TYPE_BOOL)
            {
                return new XElement("parameter", new XAttribute("name", Name), new XAttribute("type", type), Value.ToString().ToLower());
            }

            XElement xele = new XElement("parameter", new XAttribute("name", Name), new XAttribute("type", type));
            if (this.Entries != null)
            {
                foreach (var pEntry in this.Entries)
                {
                    string pEntryType = this.GetObjectType(pEntry.Value);
                    if (pEntryType == TYPE_DATETIME)
                    {
                        return new XElement("parameter", new XAttribute("name", Name), new XAttribute("type", pEntryType), ((DateTime)Value).ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                    else
                    {
                        xele.Add(new XElement("entry", new XAttribute("name", pEntry.Name), new XAttribute("type", pEntryType), pEntry.Value));
                    }
                }
            }

            return xele;
        }

        public override string ToString()
        {
            if (this.Entries != null && this.Entries.Count > 0)
            {
                return "Child: " + this.Entries.Count;
            }
            return this.Name + ":" + this.Value;
        }

    }
}
